package transaction;

import triStorage.*;

import java.util.concurrent.locks.*;
import java.util.*;

public class Transaction {
	
	private Logger logger;
	private Vector<Lock> holdingLocks;
	
	private boolean needLog;
	
	private int txNum;
	
	public Transaction(int num, Logger logger, boolean needLog) {
		holdingLocks = new Vector<Lock> ();
		this.logger = logger;
		this.txNum = num;
		
		this.needLog = needLog;
		
		this.begin();
	}
	
	private void begin() {
		if (needLog)
			logger.logBegin(txNum);
	}
	
	void getRLock(Lock lock) {
		lock.lock();
	}
	
	boolean tryRLock(Lock lock) {
		return lock.tryLock();
	}
	
	void releaseRLock(Lock lock) {
		lock.unlock();
	}
	
	void getWLock(Lock lock) {
		lock.lock();
		if (TxManager.EnableTransaction)
			holdingLocks.add(lock);
	}
	
	void releaseWLock(Lock lock) {
		if (!TxManager.EnableTransaction) 
			lock.unlock();
	}
	
	public void appendInt(TriMMPFile mmpfile, int pageId, int offset, int value) {
		if (needLog)
			logger.logAppendInt(txNum, TxManager.getFileId(mmpfile.FileName), pageId, offset, value);
	}
	
	public void appendLong(TriMMPFile mmpfile, int pageId, int offset, long value) {
		if (needLog)
			logger.logAppendLong(txNum, TxManager.getFileId(mmpfile.FileName), pageId, offset, value);
	}
	
	public void appendBytes(TriMMPFile mmpfile, int pageId, int offset, 
			byte[] value, int start, int length) {
		if (needLog)
			logger.logAppendBytes(txNum, TxManager.getFileId(mmpfile.FileName), pageId, 
					offset, value, start, length);
	}
	
	public void writeInt(TriMMPFile mmpfile, int pageId, int offset, int oldValue, int newValue) {
		if (needLog)
			logger.logWriteInt(txNum, TxManager.getFileId(mmpfile.FileName), 
					pageId, offset, oldValue, newValue);
	}
	
	public void writeLong(TriMMPFile mmpfile, int pageId, int offset, long oldValue, long newValue) {
		if (needLog)
			logger.logWriteLong(txNum, TxManager.getFileId(mmpfile.FileName), 
					pageId, offset, oldValue, newValue);
	}
	/*
	public void writeBytes(TriMMPFile mmpfile, int pageId, int offset,
			byte[] value, int start, int length) {
		//do not support
	}
	*/
	public void commit() {
		if (TxManager.EnableTransaction) {
			for (int i = 0; i < holdingLocks.size(); ++i)
				holdingLocks.get(i).unlock();
			if (needLog)
				logger.logCommit(txNum);
		}
	}
}
